const Command = @This();
const std = @import("std");

type: Type,
arg1: []const u8,
arg2: ?usize,

pub const Type = enum {
    arithmetic,
    push,
    pop,
    label,
    goto,
    @"if-goto",
    function,
    @"return",
    call,
};

pub fn parse(oneline: []const u8) !?Command {
    const line = std.mem.trimLeft(u8, oneline, " \t");
    if (line.len == 0) @panic("empty line");

    switch (line[0]) {
        '/' => return null,
        'p' => {
            var it = std.mem.tokenizeAny(u8, line[std.mem.indexOfScalar(u8, line, ' ').?..], " /");
            var arg: []const u8 = undefined;

            if (std.mem.startsWith(u8, line, "push")) {
                arg = it.next().?;
                return .{
                    .type = .push,
                    .arg1 = arg,
                    .arg2 = try std.fmt.parseInt(usize, it.next().?, 0),
                };
            } else if (std.mem.startsWith(u8, line, "pop")) {
                arg = it.next().?;
                return .{
                    .type = .pop,
                    .arg1 = arg,
                    .arg2 = try std.fmt.parseInt(usize, it.next().?, 0),
                };
            } else {
                return null;
            }
        },
        else => {
            const lastidx = for (line, 0..) |char, i| {
                switch (char) {
                    ' ', '/' => {
                        break i;
                    },
                    else => {},
                }
            } else line.len;
            const token = line[0..lastidx];

            return .{
                .type = .arithmetic,
                .arg1 = token,
                .arg2 = null,
            };
        },
    }
}
